﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
using Jamhee.Noctiluca.Common;

namespace Jamhee.Noctiluca
{
    class Noctiluca
    {
        private static DataTable _dtPorts = new DataTable();

        static void Main(string[] args)
        {
            bool success = ReadWebConfigFile();
            int exceptionCount = 0;

            if (success)
            {
                if (!HttpListener.IsSupported)
                {
                    LogUtil.PrintError("HttpListener class is not supported by your OS");
                    WaitPressKeyToExit();
                    return;
                }

                foreach (DataRow row in _dtPorts.Rows)
                {
                    try
                    {
                        LogUtil.PrintInfo("Start listening port " + row["Port"].ToString() + "...");
                        WebListener webListener = new WebListener();
                        webListener.Start((int)row["Port"], row["WebConfig"].ToString());
                    }
                    catch (Exception e)
                    {
                        exceptionCount++;
                        LogUtil.PrintError("Cannot start port " + row["Port"].ToString() + ". Error happened: " + e.Message);
                    }
                }
            }

            if (!success || exceptionCount == _dtPorts.Rows.Count)
            {
                Console.WriteLine("Press any key to exit...");
                WaitPressKeyToExit();
            }
        }

        private static bool ReadWebConfigFile()
        {
            // Initial DataTable
            _dtPorts.Columns.Add("Port", typeof(int));
            _dtPorts.Columns.Add("WebConfig", typeof(string));


            StreamReader sReader = null;
            string path = AppUtil.GetAbsolutePath(AppUtil.CONFIG_FILE_PATH + "\\" + AppUtil.WEB_CONFIG_DEF_FILE);


            // web configuration definition file doesn't exist
            if (!File.Exists(path))
            {
                return false;
            }

            try
            {
                LogUtil.PrintInfo("Reading web config definition: " + path);

                sReader = new StreamReader(path, Encoding.UTF8);
                string line = null;
                while ((line = sReader.ReadLine()) != null)
                {
                    // it's an empty line
                    if (line.Trim().Length == 0)
                    {
                        continue;
                    }

                    // it's a comment
                    if (line.Trim().StartsWith("#"))
                    {
                        continue;
                    }

                    string[] cfg = line.Split('|');
                    int port = 80;
                    bool isInteger = false;

                    if (cfg.Length == 3)
                    {
                        isInteger = Int32.TryParse(cfg[0].Trim(),out port);
                    }

                    if (isInteger)
                    {
                        // Check whether or not this port has been added
                        bool defined = false;

                        foreach (DataRow row in _dtPorts.Rows)
                        {
                            if ((int)row["Port"] == port)
                            {
                                defined = true;
                                break;
                            }
                        }

                        if (defined)
                        {
                            LogUtil.PrintWarning("The port [" + port + "] has already been defined.");
                        }
                        else
                        {
                            // Add this port only when its enable flag is 1
                            if (cfg[2].Trim().Equals("1"))
                            {
                                DataRow newRow = _dtPorts.NewRow();
                                newRow["Port"] = port;
                                newRow["WebConfig"] = cfg[1].Trim();
                                _dtPorts.Rows.Add(newRow);
                            }
                        }
                    }
                    else
                    {
                        LogUtil.PrintWarning("Skip the bad definition: " + line);
                    }
                }
            }
            catch (Exception ex)
            {
                LogUtil.PrintError("An error happened when reading web definition file: " + ex.Message);
                return false;
            }
            finally
            {
                if (sReader != null)
                {
                    sReader.Close();
                }
            }

            if (_dtPorts.Rows.Count == 0)
            {
                LogUtil.PrintInfo("Cannot find any defined web port.");
                return false;
            }

            return true;
        }

        private static void WaitPressKeyToExit()
        {
            LogUtil.PrintInfo("Press any key to exit.");
            Console.ReadKey();
        }
    }
}
